<?php

namespace catchAdmin\home\service;

use app\common\model\Followtask;
use catchAdmin\permissions\model\Users as UsersModel;
use app\common\model\PatientInfo as PatientInfoModel;
use app\common\model\Follow as FollowModel;
use app\common\model\PropagandaEducationHistory as EdHistoryModel;
use app\common\model\Contract as ContractModel;
use catchAdmin\visitPlan\model\VisitPlanDetail;
use app\common\model\DiseasePatientTask as DptModel;
use MongoDB\BSON\ObjectId;
use think\exception\FileException;

class HomeService
{
    /**
     * 获取工作台头部数据
     * @param int $user_id 用户id
     * @param string $doctor_code 医生编号
     * @return array
     */
    public function getHomeHerd(int $user_id, string $doctor_code): array
    {
        //获取当前医生信息
        $doctorInfo = (new UsersModel())->currentUserDepProInfo($user_id);
        
        //默认头像
        if (empty($doctorInfo['avatar'])) {
            $doctorInfo['avatar'] = '/files/default_avatar.png';
        }

        //获取未完成随访总数和新增已随访数
        $patientNumber = $this->getAlreadyFollowNumber($doctor_code, 0);

        //获取已随访总数和新增已随访数
        $followNumber = $this->getAlreadyFollowNumber($doctor_code, 1);

        return [
            'doctorInfo' => $doctorInfo,
            'patientNumber' => $patientNumber,
            'followNumber' => $followNumber
        ];
    }

    /**
     * 获取待办事项列表
     * @param int $user_id 用户id
     * @param string $doctor_code 医生编号
     * @param int $type 1 今天，2 近七天，3 近30天
     * @retrun array
     */
    public function getToDoList(int $user_id, string $doctor_code, int $type=1): array
    {
        //当前日期
        $currentTime = date("Y-m-d");
        $currentStamp = strtotime(date($currentTime." 23:59:59"));

        switch ($type){
            case 1:
                $date = date('Y-m-d');
                break;
            case 2:
                $date = date('Y-m-d', strtotime('-7 days'));
                break;
            case 3:
                $date = date('Y-m-d', strtotime('-30 days'));
                break;
            default:
                throw new FileException("type参数错误");
        }
        $dateStamp = strtotime(date($date." 00:00:00"));

        //获取随访计划数
        $followNum = $this->getFollowNumber($doctor_code, $date, $currentTime);

        //获取异常随访数
        $abnormalNum = $this->getAbnormalNumber($doctor_code, $date, $currentTime);

        //获取宣教计划数
        $edUnreadNum = $this->getEdNumber($user_id, $dateStamp, $currentStamp);

        //获取签约患者数
        $contractNum = $this->getContractNumber($user_id, $dateStamp, $currentStamp);

        //获取复诊计划数
        $visitNum = $this->getWaitingVisit($user_id, $dateStamp, $currentStamp);

        //获取方案处理
        $progNum = $this->getProgrammeHandle($user_id, $date, $currentTime);

        return [
            'followNum' => $followNum,
            'abnormalNum' => $abnormalNum,
            'edUnreadNum' => $edUnreadNum,
            'contractNum' => $contractNum,
            'visitNum' => $visitNum,
            'progNum' => $progNum
        ];
    }

    /**
     * 获取随访任务
     * @param string $doctor_code 医生编号
     * @retrun array
     */
    public function getFollowTask(string $doctor_code): array
    {
        $task = (new Followtask())->where([
            ['follow_staff.doctor_code', '=', $doctor_code],
            ['status', 'in', [0,1]]
        ])->column('id');

        $task_ids = array_map(function ($v) { return new ObjectId($v); }, $task);

        $totalPlanNum = (new Followtask())->where([
            ['follow_staff.doctor_code', '=', $doctor_code],
            ['status', 'in', [0,1]]
            ])->count();

        $treatNum = (new FollowModel())->where([
            ['task_id', 'in', $task_ids],
            ['follow_staff.doctor_code', '=', $doctor_code],
            ['followStatus', '=', 0]
        ])->count();

        $pip = [['$match' => ['task_id' => ['$in' => $task_ids],'follow_staff.doctor_code' => $doctor_code, 'deleted_at' => 0]], ['$group' => ['_id' => '$task_id', 'taskname' => ['$first' => '$taskname'], 'totalPlanNum' => ['$sum' => 1], 'treatNum' => ['$sum' => ['$cond' => [['$and' => [['$eq' => ['$followStatus', 0]], ['$eq' => ['$status', 0]]]], 1, 0]]], 'completeNum' => ['$sum' => ['$cond' => [['$and' => [['$eq' => ['$followStatus', 1]]]], 1, 0]]], 'abnormalNum' => ['$sum' => ['$cond' => [['$and' => [['$eq' => ['$is_effective', 0]]]], 1, 0]]]]], ['$project' => ['_id' => 0, 'task_id' => '$_id', 'taskname' => 1, 'totalPlanNum' => 1, 'treatNum' => 1, 'completeNum' => 1, 'abnormalNum' => 1, 'treatRate' => ['$multiply' => [['$cond' => [['$gt' => ['$totalPlanNum', 0]], ['$divide' => ['$treatNum', '$totalPlanNum']], 0]], 100]], 'completedRate' => ['$multiply' => [['$cond' => [['$gt' => ['$totalPlanNum', 0]], ['$divide' => ['$completeNum', '$totalPlanNum']], 0]], 100]], 'abnormalRate' => ['$multiply' => [['$cond' => [['$gt' => ['$totalPlanNum', 0]], ['$divide' => ['$abnormalNum', '$totalPlanNum']], 0]], 100]]]], ['$project' => ['_id' => 0, 'task_id' => 1, 'taskname' => 1, 'totalPlanNum' => 1, 'treatNum' => 1, 'completeNum' => 1, 'abnormalNum' => 1, 'treatRate' => ['$round' => ['$treatRate', 2]], 'completedRate' => ['$round' => ['$completedRate', 2]], 'abnormalRate' => ['$round' => ['$abnormalRate', 2]]]]];

        $list = (new FollowModel())->mongoAggregate($pip);
        foreach ($list as $key => $val) {
            $list[$key]['totalPlanNum'] = $totalPlanNum;
            $list[$key]['treatNum'] = $treatNum;
        }
        return $list;
    }

    /**
     * 获取随访情况分析图表
     * @param string $doctor_code 医生编号
     * @retrun array
     */
    public function getFollowCaseAnalysis(string $doctor_code): array
    {
        $pip = [['$match' => ['follow_staff.doctor_code' => $doctor_code, 'deleted_at' => 0]], ['$group' => ['_id' => null, 'total' => ['$sum' => 1], 'completedTasks' => ['$sum' => ['$cond' => [['$eq' => ['$followStatus', 1]], 1, 0]]], 'pendingTasks' => ['$sum' => ['$cond' => [['$and' => [['$eq' => ['$followStatus', 0]], ['$eq' => ['$status', 0]]]], 1, 0]]], 'abnormalTasks' => ['$sum' => ['$cond' => [['$eq' => ['$is_effective', 0]], 1, 0]]]]], ['$project' => ['_id' => 0, 'total' => 1, 'pendingNum' => '$pendingTasks', 'completedNum' => '$completedTasks', 'abnormalNum' => '$abnormalTasks', 'pendingRate' => ['$multiply' => [['$cond' => [['$gt' => ['$total', 0]], ['$divide' => ['$pendingTasks', '$total']], 0]], 100]], 'completedRate' => ['$multiply' => [['$cond' => [['$gt' => ['$total', 0]], ['$divide' => ['$completedTasks', '$total']], 0]], 100]], 'abnormalRate' => ['$multiply' => [['$cond' => [['$gt' => ['$total', 0]], ['$divide' => ['$abnormalTasks', '$total']], 0]], 100]]]], ['$project' => ['total' => 1, 'pendingNum' => 1, 'completedNum' => 1, 'abnormalNum' => 1, 'pendingRate' => ['$round' => ['$pendingRate', 2]], 'completedRate' => ['$round' => ['$completedRate', 2]], 'abnormalRate' => ['$round' => ['$abnormalRate', 2]]]]];
        $data = (new FollowModel())->mongoAggregate($pip);

        $ret = [];
        foreach ($data as $k => $v){
            $ret['total'] = $v['total'];
            $ret['pendingNum'] = $v['pendingNum'];
            $ret['completedNum'] = $v['completedNum'];
            $ret['abnormalNum'] = $v['abnormalNum'];
            $ret['pendingRate'] = $v['pendingRate'];
            $ret['completedRate'] = $v['completedRate'];
            $ret['abnormalRate'] = $v['abnormalRate'];
        }
        return $ret;
    }

    /**
     * 获取随访趋势分析图表
     * @param string $doctor_code 医生编号
     * @param int $type 1 近七天，2 近30天，3近一年
     * @retrun array
     */
    public function getFollowTrendAnalysis(string $doctor_code, int $type=1): array
    {
        //当前日期
        $currentTime = date("Y-m-d");

        switch ($type){
            case 1:
                $date = date('Y-m-d', strtotime('-7 days'));
                break;
            case 2:
                $date = date('Y-m-d', strtotime('-30 days'));
                break;
            case 3:
                $date = date('Y-m-d', strtotime('-1 year'));
                break;
            default:
                throw new FileException("type参数错误");
        }

        $match['follow_staff.doctor_code'] = $doctor_code;
        $match['deleted_at'] = 0;
        $match['pushtime'] = ['$lte' => $currentTime,'$gt' => $date];

        $pip = [['$match' => $match], ['$group' => ['_id' => '$pushtime', 'create_date' => ['$first' => '$pushtime'], 'total' => ['$sum' => 1], 'completedTasks' => ['$sum' => ['$cond' => [['$eq' => ['$followStatus', 1]], 1, 0]]], 'pendingTasks' => ['$sum' => ['$cond' => [['$and' => [['$eq' => ['$followStatus', 0]], ['$eq' => ['$status', 0]]]], 1, 0]]], 'abnormalTasks' => ['$sum' => ['$cond' => [['$eq' => ['$is_effective', 0]], 1, 0]]]]], ['$project' => ['_id' => 0]], ['$sort' => ['create_date' => 1]]];

        $data = (new FollowModel())->mongoAggregate($pip);

        $ret = [];
        foreach ($data as $k => $v) {
            $ret[$k]['date'] = $v['create_date'];
            $ret[$k]['details'] = [
                'total' => $v['total'],
                'completedTasks' => $v['completedTasks'],
                'pendingTasks' => $v['pendingTasks'],
                'abnormalTasks' => $v['abnormalTasks']
            ];
        }
        return $ret;
    }

    /**
     * 获取我的患者数和当日新增患者数
     * @param string $doctor_code 医生编码
     * @return array
     */
    private function getMyPatientNumber(string $doctor_code): array
    {
        $where[] = ["outList.attendingDoctorId|inList.inchargeDoctorNo|hoList.inchargeDoctorNo", 'in', [$doctor_code]];

        //总患者数
        $totalNum = (new PatientInfoModel())->where($where)->count();

        //当天0点整时间戳
        $timestamp = strtotime(date('Y-m-d 00:00:00'));

        //昨天的患者数
        $where[] = ['created_at', '<', $timestamp];
        $yesterdayNum = (new PatientInfoModel())->where($where)->count();

        return [
            'totalNum' => $totalNum, //患者总数
            'newNum' => $totalNum - $yesterdayNum //新增患者数
        ];
    }

    /**
     * 获取已随访总数和新增已随访数
     * @param string $doctor_code 医生编码
     * @param int $status 状态
     * @return array
     */
    private function getAlreadyFollowNumber(string $doctor_code, int $status): array
    {
        $where[] = ['follow_staff.doctor_code', '=', $doctor_code];
        $where[] = ['followStatus', '=', $status];

        //已随访总数
        $totalNum = (new FollowModel())->where($where)->count();

        //当天0点整时间戳
        $timestamp = strtotime(date('Y-m-d 00:00:00'));

        //昨天的已随访数
        $where[] = ['updated_at', '<', $timestamp];
        $yesterdayNum = (new FollowModel())->where($where)->count();

        return [
            'totalNum' => $totalNum, //已随访总数
            'newNum' => $totalNum - $yesterdayNum //新增已随访数
        ];
    }

    /**
     * 获取随访计划数
     * @param string $doctor_code 医生编号
     * @param string $startTime 开始日期
     * @param string $endTime 结束日期
     * @retrun array
     */
    private function getFollowNumber(string $doctor_code, string $startTime, string $endTime): array
    {
        $where[] = ['follow_staff.doctor_code', '=', $doctor_code];
        //待随访患者数
        $treatWhere[] = ['followStatus', '=', 0];
        $treatWhere[] = ['status', '=', 0];
        $treatNum = (new FollowModel())->where($where)->where($treatWhere)->count();

        //已随访患者数
        $alreadyWhere[] = ['followStatus', '=', 1];
        $alreadyWhere[] = ['pushtime', '>=', $startTime];
        $alreadyWhere[] = ['pushtime', '<=', $endTime];
        $alreadyNum = (new FollowModel())->where($where)->where($alreadyWhere)->count();

        return [
            'treatNum' => $treatNum,
            'alreadyNum' => $alreadyNum
        ];
    }

    /**
     * 获取异常随访数
     * @param string $doctor_code 医生编号
     * @param string $startTime 开始日期
     * @param string $endTime 结束日期
     * @retrun array
     */
    private function getAbnormalNumber(string $doctor_code, string $startTime, string $endTime): array
    {
        $where[] = ['follow_staff.doctor_code', '=', $doctor_code];
        $where[] = ['pushtime', '>=', $startTime];
        $where[] = ['pushtime', '<=', $endTime];
        $where[] = ['is_effective', '=', 0];
        $abnormalNum = (new FollowModel())->where($where)->count();
        return [
            'abnormalNum' => $abnormalNum
        ];
    }

    /**
     * 获取宣教计划数
     * @param int $user_id 用户id
     * @param int $startTime 开始日期
     * @param int $endTime 结束日期
     * @retrun array
     */
    private function getEdNumber(int $user_id, int $startTime, int $endTime): array
    {
        $where[] = ['creator_id', '=', $user_id];
        $where[] = ['created_at', '>=', $startTime];
        $where[] = ['created_at', '<=', $endTime];
        $where[] = ['isview', '=', 0];
        $unreadNum = (new EdHistoryModel())->where($where)->count();
        return [
            'unreadNum' => $unreadNum
        ];
    }

    /**
     * 获取签约患者数
     * @param int $user_id 用户id
     * @param int $startTime 开始日期
     * @param int $endTime 结束日期
     * @retrun array
     */
    private function getContractNumber(int $user_id, int $startTime, int $endTime): array
    {
        $where[] = ['contract_doctor.doctor_id', '=', $user_id];
        $where[] = ['created_at', '>=', $startTime];
        $where[] = ['created_at', '<=', $endTime];
        $contractNum = (new ContractModel())->where($where)->count();
        return [
            'contractNum' => $contractNum
        ];
    }

    /**
     * 获取待复诊患者数
     * @param int $user_id 用户id
     * @param int $startTime 开始日期
     * @param int $endTime 结束日期
     * @retrun array
     */
    private function getWaitingVisit(int $user_id, int $startTime, int $endTime): array
    {
        $where[] = ['creator_id', '=', $user_id];
        $where[] = ['next_visit_time', '>=', date("Y-m-d")];
        $where[] = ['status', '=', 0];
        $where[] = ['created_at', '>=', $startTime];
        $where[] = ['created_at', '<=', $endTime];
        $visitNum = (new VisitPlanDetail())->where($where)->count();
        return [
            'visitNum' => $visitNum
        ];
    }

    /**
     * 获取方案处理数
     * @param int $user_id 用户id
     * @param string $startTime 开始日期
     * @param string $endTime 结束日期
     * @retrun array
     */
    private function getProgrammeHandle(int $user_id, string $startTime, string $endTime): array
    {
        $match['doctors.doctor_id'] = 15;
        $match['deleted_at'] = 0;
        $match2['planList.plan_task_status'] = 1;
        $match2['planList.plan_date'] = ['$lte' => $endTime,'$gt' => $startTime];

        $pip = [['$match' => $match], ['$unwind' => ['path' => '$planList', 'preserveNullAndEmptyArrays' => true]], ['$match' => $match2], ['$count' => 'progNum']];
        $ret = (new DptModel())->cmd([
            'aggregate' => 'disease_patient_task',
            'pipeline' => $pip,
            'explain' => false
        ]);

        return $ret[0]??['progNum' => 0];
    }
}
